import logging
import traceback
import time
import json
import uuid
from flask import jsonify

from alipay.aop.api.AlipayClientConfig import AlipayClientConfig
from alipay.aop.api.DefaultAlipayClient import DefaultAlipayClient
from alipay.aop.api.domain.AlipayTradePagePayModel import AlipayTradePagePayModel
from alipay.aop.api.request.AlipayTradePagePayRequest import AlipayTradePagePayRequest
from alipay.aop.api.domain.AlipayTradeQueryModel import AlipayTradeQueryModel
from alipay.aop.api.request.AlipayTradeQueryRequest import AlipayTradeQueryRequest
from alipay.aop.api.response.AlipayTradeQueryResponse import AlipayTradeQueryResponse
from alipay.aop.api.domain.AlipayTradeCloseModel import AlipayTradeCloseModel
from alipay.aop.api.request.AlipayTradeCloseRequest import AlipayTradeCloseRequest
import alipay.aop.api.util.SignatureUtils as SignatureUtils

import controller.carbon_alipay.AlipayConfig as AlipayConfig

# 请求成功
success = 200
identification_error = 100  # 未识别成功


def get_uuid():
    return "".join(str(uuid.uuid4()).split("-")).lower()


class AliPayMethod(object):
    @classmethod
    def alipay_client_config(cls):
        alipay_client_config = AlipayClientConfig()
        alipay_client_config.format = AlipayConfig.format  # 设置请求格式
        alipay_client_config.charset = AlipayConfig.charset  # 设置字符集
        alipay_client_config.sign_type = AlipayConfig.signtype  # 设置请求签名类型
        alipay_client_config.server_url = AlipayConfig.server_url  # 设置支付宝网关地址
        alipay_client_config.app_id = AlipayConfig.appid  # 设置商户应用app_id
        alipay_client_config.app_private_key = AlipayConfig.app_private_key  # 设置应用私钥
        alipay_client_config.alipay_public_key = AlipayConfig.alipay_public_key  # 设置支付宝公钥
        return alipay_client_config

    @classmethod
    def create_order(cls, return_url, total_amount, subject, body, qr_pay_mode=4, qrcode_width=150):
        """
        创建订单链接
        """
        logging.debug("working on alipay paying......")
        # 得到客户端对象
        alipay_client_config = cls.alipay_client_config()
        logger = logging.getLogger('')
        client = DefaultAlipayClient(alipay_client_config=alipay_client_config, logger=logger)

        # 对照接口文档，构造请求对象
        model = AlipayTradePagePayModel()

        # 商户订单号，商户网站订单系统中唯一订单号
        trade_timestamp = time.strftime("%Y%m%d%H%M%S", time.localtime())
        time_create = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time()))
        time_expire = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time() + AlipayConfig.time_expire))
        out_trade_no = trade_timestamp + get_uuid()

        # 订单价格 & 标题 & 商品描述
        model.out_trade_no = out_trade_no
        model.total_amount = total_amount
        model.subject = subject
        model.body = body
        # 销售产品码，电脑支付场景下仅支持FAST_INSTANT_TRADE_PAY
        model.product_code = "FAST_INSTANT_TRADE_PAY"
        # 2: 订单码-跳转模式, 3: 订单码-前置模式, 4: 订单码-前置模式
        model.qr_pay_mode = qr_pay_mode
        model.qrcode_width = qrcode_width
        # 订单超时时间
        model.time_expire = time_expire

        request = AlipayTradePagePayRequest(biz_model=model)
        request.return_url = return_url
        request.notify_url = AlipayConfig.notify_url
        # 得到构造的请求，如果http_method是GET，则是一个带完成请求参数的url，如果http_method是POST，则是一段HTML表单片段
        response = client.page_execute(request, http_method="GET")

        # debug output
        logging.debug("out_trade_no: " + out_trade_no)
        logging.debug("order create time：" + time_create + ", order expire time：" + time_expire)
        logging.debug("alipay.trade.page.pay response:" + response)

        return_map = {
            'app_id': AlipayConfig.appid,
            'out_trade_no': out_trade_no,
            'time_create': time_create,
            'time_expire': time_expire,
        }

        return return_map, response

    @classmethod
    def verify_signature(cls, request):
        """
        验证签名
        """
        logging.debug("working on alipay verify_signature......")
        sign = request.values.get('sign')
        if not sign:
            return False

        keys = list(request.values.keys())
        keys.sort()
        signed_string = ""
        for key in keys:
            if key == 'sign' or key == 'sign_type':
                continue
            signed_string = signed_string + key + '='
            signed_string = signed_string + request.values.get(key) + '&'
            logging.debug(str(key) + ":" + str(request.values.get(key)))
        signed_string = signed_string[0: -1]
        signed_string = bytes(signed_string, "utf-8")
        try:
            verify_result = SignatureUtils.verify_with_rsa(AlipayConfig.alipay_public_key, signed_string, sign)
        except Exception as e:
            logging.debug("签名验证失败！")
            return False

        if not verify_result:
            logging.debug("签名验证失败！")
            return False
        return True

    @classmethod
    def _close(cls, request):
        """
        进行网站订单关闭，该方法暂时无用，暂时置为私有方法
        """
        logging.debug("working on alipay querying......")

        msg = ""
        code = success

        alipay_client_config = cls.alipay_client_config()
        logger = logging.getLogger('')
        client = DefaultAlipayClient(alipay_client_config=alipay_client_config, logger=logger)

        # 对照接口文档，构造请求对象
        model = AlipayTradeCloseModel()
        # 商户订单号 & 支付宝交易号，两者不能同时为空
        model.out_trade_no = ""
        model.trade_no = ""

        request = AlipayTradeCloseRequest(biz_model=model)
        # 得到构造的请求，如果http_method是GET，则是一个带完成请求参数的url，如果http_method是POST，则是一段HTML表单片段
        response = client.execute(request)
        print(response)
        # 处理响应

        return jsonify(code=code, data=response, msg=msg)

    @classmethod
    def query_order(cls, out_trade_no=None, trade_no=None):
        """
        获取查询订单的信息，返回值为json形式的字典量
        """
        # 商户订单号 & 支付宝交易号，两者不能同时为空
        if out_trade_no is None and trade_no is None:
            return None

        logger = logging.getLogger('')
        alipay_client_config = cls.alipay_client_config()
        client = DefaultAlipayClient(alipay_client_config=alipay_client_config, logger=logger)

        # 对照接口文档，构造请求对象
        model = AlipayTradeQueryModel()
        model.out_trade_no = out_trade_no
        model.trade_no = trade_no

        request = AlipayTradeQueryRequest(biz_model=model)
        response = client.execute(request)
        # 处理响应
        response = json.loads(response)
        return response
